home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Selection / Multimedia Selection Volume One - CD-ROM / MULTIMEDIA SELECTION____________.ISO / programz / tsrlib / remind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-30  |  8.7 KB  |  448 lines

  1. /*        Screen Clock /Reminder.
  2.         -----------------------
  3.  
  4.     Roger Dalton of R&D Associates.
  5.  
  6. */
  7.  
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <bios.h>
  12. #include <time.h>
  13.  
  14. #include "tsrlib.h"
  15.  
  16.  
  17. /* Table must exist! */
  18.  
  19. HOTKEY hotkey_table[] = {
  20.     KEYCODE(52, CTRL | ALT),    /* CTRL-ALT-'.' */
  21.     LAST_KEY                    /* no hotkeys needed */
  22. };
  23.  
  24.  
  25. /* Signature must exist! */
  26.  
  27. char signature[] = "REMINDER";
  28.  
  29.  
  30. /* Structure to hold DOS time. */
  31.  
  32. typedef struct {
  33.     int hour;
  34.     int min;
  35.     int sec;
  36.     int hsec;
  37. } TIMES;
  38.  
  39.  
  40. /* Specify only what you need. If you won't need a heap, specify a
  41. small value like this as 0 means 'use all possible'. NOTE: Turbo C2.0
  42. users can't specify less than about 512 anyway! */
  43.  
  44. unsigned int _heaplen = 512;
  45. unsigned int _stklen = 512;
  46.  
  47.  
  48. unsigned int far *screen;        /* pointer to video screen */
  49.  
  50. char screen_save[8000];            /* screen save buffer */
  51.  
  52. char alarm_time[6];                /* buffer for alarm time */
  53. char alarm_message[36];            /* buffer for alarm message */
  54.  
  55. int alarm_set = 0;
  56. int alarm_hour = 0;
  57. int alarm_min = 0;                /* current alarm time */
  58.  
  59. /* PROTOTYPES */
  60.  
  61. void get_time(TIMES *timerp);
  62. int get_mode(void);
  63. void get_user_alarm_time(void);
  64. void do_alarm(void);
  65. void draw_box(int r1, int c1, int r2, int c2, int attr);
  66. int get_string(int row, int col, char *buf, int size, int attr);
  67. void draw_string(int row, int col, char *string, int attr);
  68. void write_at(int row, int col, int *buf, int len);
  69. void set_cursor_style(int style);
  70. int get_cursor_style(void);
  71. int get_cursor_position(void);
  72. void set_cursor_position(int row, int col);
  73. void beep(void);
  74.  
  75.  
  76.  
  77. /* The main program. The only possibilites are:
  78.  
  79.     remind foreground
  80. or
  81.     remind foreground background
  82. */
  83.  
  84. main(argc, argv)
  85. int argc;
  86. char **argv;
  87. {
  88.     TIMES tim;                        /* time structure */
  89.     int mode;                        /* video mode */
  90.     unsigned int chr;                /* buffer for characters */
  91.     unsigned int attr = 0x7000;        /* screen sttribute */
  92.     int i;                            /* loop counter */
  93.     int flip = 0;                    /* colon ticker */
  94.     char tmp[32];                    /* time string buffer */
  95.     static char tick[] = ": ";
  96.     int old_sec = 0;
  97.  
  98.     if (resident_tsr()) {
  99.         printf("%s is already resident.\n", signature);
  100.         exit(1);
  101.     }
  102.     printf("%s is loaded.\n", signature);
  103.  
  104.     if (argc > 1) {
  105.         attr &= 0xf000;
  106.         attr |= atoi(argv[1]) << 8;
  107.     }
  108.  
  109.     if (argc > 2) {
  110.         attr &= 0x0f00;
  111.         attr |= atoi(argv[2]) << 12;
  112.     }
  113.  
  114.     screen = (unsigned int far *)((get_mode() == 7)? 0xb0000000L: 0xb8000000L);
  115.  
  116.     /* Past here CAN'T use printf etc. */
  117.  
  118.     go_tsr(SLEEP, 1);
  119.  
  120.     while (1) {
  121.         mode = get_mode();
  122.         if (mode == 7 || mode == 3 || mode == 2) {
  123.  
  124.             if (mode == 7) {
  125.                 attr = 0x7000;
  126.             }
  127.  
  128.             get_time(&tim);
  129.             if (tim.sec != old_sec) {
  130.                 flip ^= 1;                /* flip the colon */
  131.             }
  132.             old_sec = tim.sec;
  133.             sprintf(tmp, " %02d%c%02d%c%02d %c ", tim.hour, tick[flip],
  134.                     tim.min, tick[!flip], tim.sec, " *"[alarm_set]);
  135.  
  136.             for (i = 0; (chr = tmp[i]); i++) {
  137.                 screen[35 + i] = chr | attr;
  138.             }
  139.  
  140.             if (alarm_set && tim.hour >= alarm_hour && tim.min >= alarm_min) {
  141.                 do_alarm();
  142.             }
  143.         }
  144.  
  145.         /* If our hot key was pressed, save the screen as we will be writing on
  146.         it. */
  147.  
  148.         if (suspend_tsr(SLEEP, 4) == RUNNING) {
  149.             get_user_alarm_time();
  150.         }
  151.     }
  152. }
  153.  
  154.  
  155.  
  156.  
  157. /* Function to read DOS date & time, and build the structure. */
  158.  
  159. void get_time(TIMES *timerp)
  160. {
  161.     union REGS regs;
  162.  
  163.     regs.h.ah = 0x2c;
  164.     int86(0x21, ®s, ®s);
  165.     timerp->hour = regs.h.ch;
  166.     timerp->min = regs.h.cl;
  167.     timerp->sec = regs.h.dh;
  168.     timerp->hsec = regs.h.dl;
  169. }
  170.  
  171.  
  172.  
  173.  
  174. /* Return the current display mode. */
  175.  
  176. int get_mode(void)
  177. {
  178.     _AH = 0x0f;
  179.     geninterrupt(0x10);
  180.     return _AL;
  181. }
  182.  
  183.  
  184.  
  185. /* Procedure to draw a prompt box, and get an alarm time from the user. */
  186.  
  187. void get_user_alarm_time(void)
  188. {
  189.     char tmp[10];
  190.  
  191.     /* Save screen */
  192.  
  193.     movedata(FP_SEG(screen), 0, _DS, (unsigned)screen_save, 8000);
  194.  
  195.     draw_box(10, 15, 13, 65, 0x3000);                /* black on cyan */
  196.     draw_string(11, 17, "Alarm time: ", 0x3f00);    /* bright white on cyan */
  197.     draw_string(12, 17, "   Message: ", 0x3f00);    /* bright white on cyan */
  198.     draw_string(12, 29, alarm_message, 0x3f00);
  199.  
  200.     /* Get the alarm time. */
  201.  
  202.     sprintf(alarm_time, "%02d:%02d", alarm_hour, alarm_min);
  203.     do {
  204.         beep();
  205.         if (get_string(11, 29, alarm_time, sizeof(alarm_time) - 1, 0x3f00)) {
  206.             goto done;
  207.         }
  208.         tmp[0] = alarm_time[0];
  209.         tmp[1] = alarm_time[1];
  210.         tmp[2] = '\0';
  211.         tmp[3] = alarm_time[3];
  212.         tmp[4] = alarm_time[4];
  213.         tmp[5] = '\0';
  214.     } while ((alarm_hour = atoi(tmp)) >= 24
  215.             || (alarm_min = atoi(tmp + 3)) >= 60);
  216.     alarm_set = 1;
  217.  
  218.     /* Get the alarm message. */
  219.  
  220.     get_string(12, 29, alarm_message, sizeof(alarm_message) - 1, 0x3f00);
  221.  
  222.     /* Restore screen */
  223. done:
  224.     movedata(_DS, (unsigned)screen_save, FP_SEG(screen), 0, 8000);
  225. }
  226.  
  227.  
  228.  
  229.  
  230. /* Procedure to display the alarm time and message, and wait for ESCAPE to
  231. be pressed. */
  232.  
  233. void do_alarm(void)
  234. {
  235.     clock_t now;
  236.     int toggle = 0;
  237.     char tmp[40];
  238.  
  239.     _TS_tsr_state = RUNNING;                    /* don't pre-empt */
  240.  
  241.     /* Save screen */
  242.  
  243.     movedata(FP_SEG(screen), 0, _DS, (unsigned)screen_save, 8000);
  244.  
  245.     draw_box(10, 15, 13, 65, 0x4f00);            /* bright white on red */
  246.     sprintf(tmp, "*** ALARM AT %2d:%02d ***", alarm_hour, alarm_min);
  247.     draw_string(11, 29, tmp, 0x4f00);
  248.     sprintf(tmp, "  Message: %s", alarm_message);
  249.     draw_string(12, 17, tmp, 0x4f00);
  250.  
  251.     beep();
  252.     now = clock();
  253.     do {
  254.         while (bioskey(1) == 0) {
  255.             if (clock() >= now + 9 + toggle * 9) {
  256.                 beep();
  257.                 now = clock();
  258.                 toggle ^= 1;
  259.             }
  260.         }
  261.     } while ((bioskey(0) & 0xff) != 0x1b);
  262.  
  263.     alarm_set = 0;
  264.  
  265.     /* Restore screen */
  266.  
  267.     movedata(_DS, (unsigned)screen_save, FP_SEG(screen), 0, 8000);
  268. }
  269.  
  270.  
  271.  
  272.  
  273. /* Procedure to draw a box from top left to bottom right. NOTE: to avoid sign
  274. extension on graphics characters, they must by masked with 0xff. This does not
  275. generate any more code. */
  276.  
  277. void draw_box(int r1, int c1, int r2, int c2, int attr)
  278. {
  279.     int i, j;
  280.     int tmp[80];            /* draw buffer */
  281.  
  282.     j = c2 - c1 + 1;
  283.     tmp[0] = attr | ('╔' & 0xff);
  284.     for (i = 1; i < j - 1; i++) {
  285.         tmp[i] = attr | ('═' & 0xff);
  286.     }
  287.     tmp[j - 1] = attr | ('╗' & 0xff);
  288.     write_at(r1, c1, tmp, j);
  289.     tmp[0] = attr | ('╚' & 0xff);
  290.     tmp[j - 1] = attr | ('╝' & 0xff);
  291.     write_at(r2, c1, tmp, j);
  292.     tmp[0] = attr | ('║' & 0xff);
  293.     tmp[j - 1] = attr | ('║' & 0xff);
  294.     for (i = 1; i < j - 1; i++) {
  295.         tmp[i] = attr | ' ';
  296.     }
  297.     for (i = r1 + 1; i < r2; i++) {
  298.         write_at(i, c1, tmp, j);
  299.     }
  300. }
  301.  
  302.  
  303.  
  304.  
  305. /* Procedure to read a string from the user at a given screen position. Returns
  306. when RETURN is pressed. */
  307.  
  308. int get_string(int row, int col, char *buf, int size, int attr)
  309. {
  310.     int key;
  311.     int c;
  312.     int old_pos = get_cursor_position();
  313.     int old_style = get_cursor_style();
  314.  
  315.     c = 0;
  316.     set_cursor_style(0x001f);
  317.     for (;;) {
  318.         set_cursor_position(row, c + col);    /* position the cursor */
  319.         buf[size] = '\0';
  320.         draw_string(row, col, buf, attr);
  321.         key = bioskey(0);
  322.         if (key & 0xff) {
  323.             key &= 0xff;
  324.             if (key == 0x1b) {
  325.                 set_cursor_style(old_style);
  326.                 set_cursor_position(old_pos >> 8, old_pos);
  327.                 return 1;                /* aborted by ESCAPE */
  328.             }
  329.             if (key >= ' ') {
  330.                 if (c < size) {
  331.                     buf[c] = key;        /* standard ASCII keys */
  332.                     ++c;
  333.                 }
  334.             } else if (key == '\r' || key == '\n') {
  335.                 set_cursor_style(old_style);
  336.                 set_cursor_position(old_pos >> 8, old_pos);
  337.                 return 0;                /* done! */
  338.  
  339.             } else if (key == '\b') {
  340.                 if (c) {
  341.                     --c;                /* backspace */
  342.                 }
  343.             }
  344.         } else {
  345.             key >>= 8;
  346.             if (key == 75) {
  347.                 if (c) {
  348.                     --c;                /* left arrow */
  349.                 }
  350.             } else if (key == 77) {
  351.                 if (c < size) {
  352.                     ++c;                /* right arrow */
  353.                 }
  354.             }
  355.         }
  356.     }
  357. }
  358.  
  359.  
  360.  
  361.  
  362. /* Procedure to draw a string on the screen. */
  363.  
  364. void draw_string(int row, int col, char *string, int attr)
  365. {
  366.     int i, t;
  367.     int tmp[80];
  368.  
  369.     for (i = 0; i < 80; i++) {
  370.         if ((t = *string++) == '\0') {
  371.             break;
  372.         }
  373.         tmp[i] = attr | t;
  374.     }
  375.     write_at(row, col, tmp, i);
  376. }
  377.  
  378.  
  379.  
  380.  
  381. /* Procedure to write an array of cells to the screen. */
  382.  
  383. void write_at(int row, int col, int *buf, int len)
  384. {
  385.     unsigned int far *scp = &screen[row * 80 + col];
  386.  
  387.     while (len-- > 0) {
  388.         *scp++ = *buf++;
  389.     }
  390. }
  391.  
  392.  
  393.  
  394.  
  395. void set_cursor_style(int style)
  396. {
  397.     int mode = get_mode();
  398.  
  399.     _AL = mode;                        /* avoid AMI 386 BIOS bug */
  400.     _AH = 0x01;
  401.     _CX = style;
  402.     geninterrupt(0x10);
  403. }
  404.  
  405.  
  406.  
  407.  
  408. int get_cursor_style(void)
  409. {
  410.     _BH = 0;
  411.     _AH = 0x03;
  412.     geninterrupt(0x10);
  413.     return _CX;
  414. }
  415.  
  416.  
  417.  
  418.  
  419. int get_cursor_position(void)
  420. {
  421.     _BH = 0;
  422.     _AH = 0x03;
  423.     geninterrupt(0x10);
  424.     return _DX;
  425. }
  426.  
  427.  
  428.  
  429.  
  430. void set_cursor_position(int row, int col)
  431. {
  432.     _BX = 0;
  433.     _DH = row;
  434.     _DL = col;
  435.     _AH = 0x02;
  436.     geninterrupt(0x10);
  437. }
  438.  
  439.  
  440.  
  441.  
  442. void beep(void)
  443. {
  444.     _AX = 0x0e07;
  445.     _BX = 0;
  446.     geninterrupt(0x10);
  447. }
  448.